package top.codef.secure.config.delegates;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.context.SecurityContextRepository;

import top.codef.secure.components.CerberusSecurityContextHolderStrategy;
import top.codef.secure.components.RedisSecurityContextRepository;
import top.codef.secure.components.RestHeaderTokenLogoutHandler;
import top.codef.secure.config.interfaces.CerberusHttpSecurityConfig;
import top.codef.secure.properties.CerberusRestHeaderProperties;

@Configuration
@EnableConfigurationProperties(CerberusRestHeaderProperties.class)
@ConditionalOnClass({ RedisTemplate.class })
@ConditionalOnProperty(name = "cerberus.secure.rest-header.enabled", havingValue = "true")
@Order(2)
public class CerberusRestHeaderConfig implements CerberusHttpSecurityConfig {

	@Autowired
	private CerberusRestHeaderProperties cerberusRestHeaderProperties;

	private final Log logger = LogFactory.getLog(CerberusRestHeaderConfig.class);

	@Override
	public void secure(HttpSecurity httpSecurity) throws Exception {
		logger.debug("rest header 设置");
		httpSecurity.csrf(x -> x.disable()).sessionManagement(x -> x.disable());
		httpSecurity.securityContext(x -> x.securityContextRepository(redisSecurityContextRepository()))
				.logout(x -> x.addLogoutHandler(restHeaderTokenLogoutHandler()));
	}

	@Autowired
	@Qualifier("securityRedisTemplate")
	RedisTemplate<String, Object> securityRedisTemplate;

	@Bean
	public SecurityContextHolderStrategy securityContextHolderStrategy(
			SecurityContextRepository securityContextRepository) {
		logger.debug("新建securityContextHolder策略");
		return new CerberusSecurityContextHolderStrategy(securityContextRepository);
	}

	@Bean
	public RedisSecurityContextRepository redisSecurityContextRepository() {
		RedisSecurityContextRepository securityContextRepository = new RedisSecurityContextRepository(
				securityRedisTemplate, cerberusRestHeaderProperties);
		return securityContextRepository;
	}

	@Bean
	public RestHeaderTokenLogoutHandler restHeaderTokenLogoutHandler() {
		RestHeaderTokenLogoutHandler restHeaderTokenLogoutHandler = new RestHeaderTokenLogoutHandler(
				redisSecurityContextRepository());
		return restHeaderTokenLogoutHandler;
	}

}
